package JMH.day04;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 多线程：
 Benchmark                                         Mode  Cnt  Score    Error  Units
 JMH.day04.ReentrantLockVsSynchronized02.base      avgt   10  0.006 ±  0.001  us/op
 JMH.day04.ReentrantLockVsSynchronized02.lock      avgt   10  0.281 ±  0.004  us/op
 JMH.day04.ReentrantLockVsSynchronized02.readLock  avgt   10  1.701 ±  0.067  us/op
 JMH.day04.ReentrantLockVsSynchronized02.sync      avgt   10  0.362 ±  0.002  us/op
 *
 * Lock性能好。
 */
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 10)
@Measurement(iterations = 10)
@BenchmarkMode(Mode.AverageTime)
public class ReentrantLockVsSynchronized02 {

    @State(Scope.Group)
    public static class Test {

        private int x = 0;
        private final ReentrantLock lock = new ReentrantLock();
        private final Lock readLock = new ReentrantReadWriteLock().readLock();

        public int baseMethod() {
            return x;
        }

        public int lockMethod() {
            lock.lock();
            try {
                return x;
            } finally {
                lock.unlock();
            }
        }

        public int syncMethod() {
            synchronized (this) {
                return x;
            }
        }

        public int readLockMethod() {
            readLock.lock();
            try {
                return x;
            } finally {
                readLock.unlock();
            }
        }
    }

    @GroupThreads(10)
    @Group("base")
    @Benchmark
    public void testBase(Test test, Blackhole blackhole) {
        blackhole.consume(test.baseMethod());
    }

    @GroupThreads(10)
    @Group("sync")
    @Benchmark
    public void testSync(Test test,Blackhole blackhole) {
        blackhole.consume(test.syncMethod());
    }

    @GroupThreads(10)
    @Group("lock")
    @Benchmark
    public void testLock(Test test,Blackhole blackhole) {
        blackhole.consume(test.lockMethod());
    }

    @GroupThreads(10)
    @Group("readLock")
    @Benchmark
    public void testReadLock(Test test,Blackhole blackhole) {
        blackhole.consume(test.readLockMethod());
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(ReentrantLockVsSynchronized02.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(options).run();
    }
}